<?php

class ComponentPluginController extends GenesisController {

    /**
     * Returns the relevant component's db model class
     *
     * @param string $componentName
     * @param string $componentTable
     * @return mixed
     */
    private function _getComponentModel($componentName,$componentTable) {
       $componentsDir=$this->_config->components->path;

       $component = new Default_Model_Components();
       $component->findOneByName($componentName);

       $componentLocation=$component->getLocation();

       $config = $this->_getComponentIniFile($component);

       if (!isset($config->db->table->$componentTable))
           throw new Exception("db table labled '$componentTable' not found in ini file");

       $table=$config->db->table->$componentTable;

       $tmp = explode('_',ucfirst($table));
       $dbClassFile='';

       foreach ($tmp as $word)
        $dbClassFile.=ucfirst($word);

       require($componentsDir.DIRECTORY_SEPARATOR.$componentLocation.DIRECTORY_SEPARATOR.'php'.DIRECTORY_SEPARATOR.'model'.DIRECTORY_SEPARATOR.$dbClassFile.'.php');

       $modelClassName='Default_Model_'.$dbClassFile;
       $componentModel = new $modelClassName();
       return $componentModel;

    }


   /**
    *
    * Loads the relevant config.ini into a Zend_Config_ini class
    *
    * @param  Default_Model_Components $component
    * @return Zend_Config_Ini
    */
    private function _getComponentIniFile($component) {

        if (!($component instanceof Default_Model_Components)) {
            throw new Exception("component is not a valid db object!");
        }

        $location = $component->getLocation();
        $componentsDir=$this->_config->components->path;
        $iniFile=$componentsDir.DIRECTORY_SEPARATOR.$location.DIRECTORY_SEPARATOR.'ini'.DIRECTORY_SEPARATOR.$location.'.ini';

        if (!is_file($iniFile))
            throw new Exception("component missing main ini file $location.ini");

        return new Zend_Config_Ini($iniFile,'default');

    }

    /**
     * Returns the relevant component's class
     *
     * @param Default_Model_Config $component
     * @param Zend_Config_Ini $config
     * @param array $params
     * @return Component_Class
     */

    private function _getComponentClassFile($component,$config,$params=array(),$label='label') {
        if (!$label)
            $label='label';
        $location = $component->getLocation();
        $componentsDir=$this->_config->components->path;
        $classFile=$componentsDir.DIRECTORY_SEPARATOR.$location.DIRECTORY_SEPARATOR.'php'.DIRECTORY_SEPARATOR.$config->php->mainfile;
        $className = $config->php->classname;
        $imagesUri=$this->_config->images->uri;
        require($classFile);
        
        $class = new $className($this->_config->jqgrid->theme,$componentsDir,$location,$imagesUri,$params,$label);

        return $class;


    }

    /**
     * Shows the releveant component table in a grid, and sets required vars for
     * the view.
     *
     * Requires:_REQUEST['name']                , _REQUEST['table']
     *          _REQUEST['table_element_name']  , _REQUEST['col_names']
     *          _REQUEST['col_model']           , _REQUEST['row_num']
     *          _REQUEST['row_list']            , _REQUEST['jq_grid_theme']
     *          _REQUEST['sort_name']           , _REQUEST['sort_order']
     *          _REQUEST['title']               , _REQUEST['primary_key']
     *
     * Returns: Sets all above vars in the view to their values.
     */

    public function showComponentTableGridAction() {

       $this->view->headScript()->appendFile('/js/jquery/jquery.json-2.2.js');

       $componentName=$this->_request->getParam('name');
       $componentTable=$this->_request->getParam('table');
       $tableElementName=$this->_request->getParam('table_element_name');
       $colNames=$this->_request->getParam('col_names');
       $colModel=$this->_request->getParam('col_model');
       $rowNum=$this->_request->getParam('row_num');
       $rowList=$this->_request->getParam('row_list');
       $jqGridTheme=$this->_request->getParam('jq_grid_theme');
       $sortName=$this->_request->getParam('sort_name');
       $sortOrder=$this->_request->getParam('sort_order');
       $title=$this->_request->getParam('title');
       $primaryKey=$this->_request->getParam('primary_key');
       
       $this->view->componentName=$componentName;
       $this->view->componentTable=$componentTable;
       $this->view->tableElementName=$tableElementName;
       $this->view->colNames=$colNames; // ['Id','Label','Content','Actions']
       $this->view->colModel=$colModel;
       $this->view->rowNum=$rowNum;
       $this->view->jqGridTheme=$jqGridTheme;
       $this->view->sortName=$sortName;
       $this->view->sortOrder=$sortOrder;
       $this->view->title=$title;
       $this->view->rowList=$rowList;
       $this->view->primaryKey=$primaryKey;
       
    }

    /**
     * Shows the relevant component's config page
     *
     * Requires: _REQUEST['id']
     */

    public function getComponentConfigPageAction() {

        $this->view->headScript()->appendFile('/js/jquery/jquery.json-2.2.js');
        $this->view->headLink()->appendStylesheet('/js/jqGrid/themes/ui.jqgrid.css');
        $this->view->headScript()->appendFile('/js/jqGrid/js/i18n/grid.locale-en.js');
        $this->view->headScript()->appendFile('/js/jqGrid/js/jquery.jqGrid.js');

        $id = $this->_request->getParam('id');
         if (!is_numeric($id)) {
             $this->view->message='id not vaild';
         }
          else {
            $component = new Default_Model_Components();
            $component->find($id);
            $config=$this->_getComponentIniFile($component);
            $class=$this->_getComponentClassFile($component, $config);
            $message=$class->getConfigPage();
            $this->view->message=$message;

         }

     }


    /**
     * Shows the extended options of the relevant components.
     *
     * Required: _REQUEST['id']
     */
     public function getComponentLabelOptionsAreaAction() {
                     
         $id = $this->_request->getParam('id');
         if (!is_numeric($id)) {
             $this->view->message='id not vaild';
         }
          else {

            $component = new Default_Model_Components();
            $component->find($id);
            $config=$this->_getComponentIniFile($component);
            $class=$this->_getComponentClassFile($component, $config);
            $message=$class->getOptionsDiv();
            $this->view->message=$message;

         }
         
     }

     /**
      * Parse the relevant component's template file and display it
      *
      * Required: _REQUEST['component'], _REQUEST['template']
      *
      */
     public function showComponentWindowAction() {
        $this->view->headScript()->appendFile('/js/jquery/jquery.json-2.2.js');

        $componentName=$this->_request->getParam('component');
        $template=$this->_request->getParam('template');
        $component = new Default_Model_Components();
        $component->findOneByName($componentName);

        if (!$component->getId())
           throw new Exception("component name '$componentName' not found! contact admin.");

        $config=$this->_getComponentIniFile($component);
        $class=$this->_getComponentClassFile($component, $config);

        if (!isset($config->phtml->$template))
            throw new Exception("component $componentName is missing template definition $template.");

        $this->view->headLink()->appendStylesheet('/js/jqGrid/themes/ui.jqgrid.css');
        $this->view->headScript()->appendFile('/js/jqGrid/js/i18n/grid.locale-en.js');
        $this->view->headScript()->appendFile('/js/jqGrid/js/jquery.jqGrid.js');

        $phtmlName=$config->phtml->$template;

        $ret=$class->getTmplContent($phtmlName);
        $this->view->content=$ret;

    }
   
    /**
     * Handler for add, del, and edit action of relevant component's jqGrid.
     *
     * Requires: _REQUEST['name']   , _REQUEST['table']
     *           _REQUEST['id']
     *           _REQUEST['oper'] - operation to perform
     */

    public function setComponentTableRowJsonAction() {

       $componentName=$this->_request->getParam('name');
       $componentTable=$this->_request->getParam('table');
       $id=$this->_request->getParam('id');
       $oper = $this->_request->getParam('oper');
       
       $componentModel=$this->_getComponentModel($componentName, $componentTable);
       $primaryKey = $componentModel->getMapper()->getDbTable()->getPrimaryKeyName();
       
       if (in_array($oper,array('edit','del')))
           $componentModel->find($id);
       if ($oper == 'del' ) {
           $componentModel->deleteRowByPrimaryKey();
       } else {

       unset($_POST['oper']);
       
       foreach ($_POST as $key=>$value) {
           if ($key == 'id')
               continue;
           $parseKey='set'.$componentModel->columnName2Var($key);
           $componentModel->$parseKey($value);
       }
       $componentModel->save();
       }


    }

    /**
     * Gets component's table from db according to page, rows, sidx and sord.
     *
     * Requires: _REQUEST['name'] , _REQUEST['table']
     *           _REQUEST['page'] , _REQUEST['rows']
     *           _REQUEST['sidx'] , _REQUEST['sord']
     *
     * Returns: Array where 'page'    => Page number
     *                      'total'   => Total number of pages
     *                      'records' => Total number of rows
     *                      'rows'    => Component usage rows as an Array
     *          Returned as json message in $view->jsonMessage
     */

    public function getComponentTableJsonAction() {

       $componentName=$this->_request->getParam('name');
       $componentTable=$this->_request->getParam('table');

        $page = $this->_request->getParam('page'); // get the requested page
        $limit = $this->_request->getParam('rows'); // get how many rows we want to have into the grid
        $sidx = $this->_request->getParam('sidx'); // get index row - i.e. user click to sort
        $sord = $this->_request->getParam('sord'); // get the direction if(!$sidx) $sidx =1;

       $componentModel=$this->_getComponentModel($componentName, $componentTable);
       $records = $componentModel->countAllRows();

        $total=ceil(($records)/$limit);
        if ($page > $total)
                $page=$total;


    $rows=array();
    if ($records>0) $rows=$componentModel->fetchListToArray(null, $sidx.' '.$sord, $limit, ($page-1)*$limit);
       $primaryKey=$componentModel->getMapper()->getDbTable()->getPrimaryKeyName();

       
       //TODO: currently the first row has to be the primary key.
       $resultRows=array();
       foreach ($rows as $row) {
           $data=array();
           foreach ($row as $value) {
               $data[]=$value;
           }
           $resultRows[]=array(
                'id'=>$row[$primaryKey],
                'cell' => $data
               );

       }

       $ret = array(
            'page'=>$page,
            'total'=>$total,
            'records'=>$records,
            'rows'=>$resultRows);
        $this->view->jsonMessage=json_encode($ret);


    }

    
    /**
     * Displays the demo page of the requested component.
     *
     * Required: _REQUEST['id']
     */

    public function getComponentDemoAction() {

        $id = $this->getRequest()->getParam('id');

        if (!is_numeric($id))
                throw new Exception("row_id missing!");

        $component = new Default_Model_Components();
        $component->find($id);

        $config=$this->_getComponentIniFile($component);
        $class=$this->_getComponentClassFile($component, $config);

        $location=$component->getLocation();
        $componentDir=$this->_config->components->path.DIRECTORY_SEPARATOR.$location.DIRECTORY_SEPARATOR;
        $phpFile=$componentDir.DIRECTORY_SEPARATOR.'php'.DIRECTORY_SEPARATOR.$config->php->mainfile;
        $iniFile=$componentDir.DIRECTORY_SEPARATOR.'ini'.DIRECTORY_SEPARATOR.$location.'.ini';
        $config = new Zend_Config_Ini($iniFile, 'default');
        $className=$config->php->classname;

        require_once($phpFile);
        $location = $component->getLocation();
        $componentsDir=$this->_config->components->path;
        $imagesUri=$this->_config->images->uri;

        $class = new $className($this->_config->jqgrid->theme,$componentsDir,$location,$imagesUri);
        $ret=$class->demo();
        $this->view->code=$ret;

    }

    /**
     * Displays a component
     * It is possible to get paramaters as a json encoded string called params
     * or as get/post variables.
     *
     * Requires: _REQUEST['id'] , _REQUEST['params']
     *           _REQUEST['label']
     */

    public function getComponentAction() {

        $id = $this->getRequest()->getParam('id');
        $params = $this->getRequest()->getParam('params');
        $label = $this->getRequest()->getParam('label');
        
        if (!is_numeric($id))
                throw new Exception("row_id missing!");

        if ($params=='') {
            $params=array();
                foreach ($this->getRequest()->getParams() as $key=>$value) {
                    if (in_array($key,array('id','params','controller','action','module','label')))
                            continue;
                 $params[$key]=$value;
            }
        } else  
               $params = json_decode($params,true);
        
        $component = new Default_Model_Components();
        $component->find($id);
        $config=$this->_getComponentIniFile($component);
        $class=$this->_getComponentClassFile($component, $config,$params,$label);
        $ret=$class->show();
        $this->view->code=$ret;
    }

}